# -*- coding:utf-8 -*-
import re
import os

class ValidateForm():
	def __init__(self):
		pass

	def fm_valid(self,  handler, fm_name, fm_type=None, fm_reg='.*', required=True, err_msg=None):
		"""
		表单验证
		大致分三类：input\checkbox\file
		:param handler:
		:param fm_name: 字段的name属性值
		:param fm_type: 字段的type属性值，也可为获取该字段值的方法（考虑到其他框架的扩展，所以...）
		:param fm_reg: 验证字段的正则
		:param required: 字段是否可以为空
		:param err_msg: 验证错误时的提示信息，为字典类型>>>err_msg格式为{'empty':'','format':''}，可全写可写任一也可全不写，"empty"表示空时的提示，"format"表示正则不匹配时的提示(key名称正确才生效)
		:return:
		"""

		ret = {}

		is_valid = True
		fm_value = None
		err_message = ''

		err_msg_dic = {}
		if type(err_msg) == dict:
			err_msg_dic.update(err_msg)

		if not fm_type or fm_type == 'text' or fm_type == 'password' or fm_type == 'self.get_argument()':
			fm_value = handler.get_argument(fm_name)  # 获取表单的值

			if not required:  # 允许为空，则直接返回表单值（required为False时）
				is_valid = True
				err_message = ''
				if not fm_value:
					fm_value = None

			else:  # 不允许为空
				if not fm_value.strip():  # 表单值为空时，则直接返回错误信息
					if 'empty' not in err_msg_dic.keys():  # err_msg为默认值None时，则设置err_message
						err_message = '{}不能为空'.format(fm_name)
					else:  # err_msg有传值时，则直接返回err_message
						err_message = err_msg_dic['empty']
					is_valid = False
					fm_value = None
				else:  # 表单值不为空时，则进行fm_reg正则匹配
					ret_re = re.match(fm_reg, fm_value)
					if ret_re:  # 匹配成功
						is_valid = True
						err_message = ''
					else:  # 匹配失败
						if 'format' not in err_msg_dic.keys():  # err_msg为默认值None时，则设置err_message
							err_message = '{}格式不正确'.format(fm_name)
						else:  # err_msg有传值时，则直接返回err_message
							err_message = err_msg_dic['format']
						is_valid = False
						fm_value = None

		elif fm_type == 'checkbox' or fm_type == 'self.get_arguments()':
			fm_value = handler.get_arguments(fm_name)

			if not required:
				is_valid = True
				err_message = ''
				if not fm_value:
					fm_value = []  # 为了防止>>>无值时，循环取值会报`'NoneType' object is not iterable`的问题

			else:
				if not len(fm_value):
					if 'empty' not in err_msg_dic.keys():
						err_message = '{}不能为空'.format(fm_name)
					else:
						err_message = err_msg_dic['empty']
					is_valid = False
					fm_value = []
				else:
					for v_checkbox in fm_value:
						ret_re = re.match(fm_reg, v_checkbox)
						if ret_re:
							is_valid = True
							err_message = ''
						else:
							if 'format' not in err_msg_dic.keys():
								err_message = '{}格式不正确'.format(fm_name)
							else:
								err_message = err_msg_dic['format']
							is_valid = False
							fm_value = []

		elif fm_type == 'file' or fm_type == 'self.request.files[]':

			if not required:
				is_valid = True
				err_message = ''
				try:
					file_obj = handler.request.files[fm_name]
					for meta in file_obj:
						file_name = meta['filename']
						if not file_name:
							fm_value = None
						else:
							fm_value = file_name
				except:
					fm_value = None

			else:
				# fm_values = []  # 若考虑同一个fm_name用于多个文件，则可用列表接收文件名
				# err_msgs = []  # 同理，若考虑...  err_msgs追加有点不好搞
				# 所以不考虑同一个fm_name用于多个文件的情况
				try:
					file_obj = handler.request.files[fm_name]
					for meta in file_obj:
						file_name = meta['filename']
						if not file_name:
							if 'empty' not in err_msg_dic.keys():
								err_message = '{}不能为空'.format(fm_name)
							else:
								err_message = err_msg_dic['empty']
							is_valid = False
							fm_value = None
						else:
							ret_re = re.match(fm_reg, file_name)
							if ret_re:
								is_valid = True
								err_message = ''
								fm_value = file_name
								# fm_values.append(file_name)
								# fm_value = fm_values
							else:
								if 'format' not in err_msg_dic.keys():
									err_message = '{}格式不正确'.format(fm_name)
								else:
									err_message = err_msg_dic['format']
								is_valid = False
								fm_value = None
				except:
					if 'empty' not in err_msg_dic.keys():
						err_message = '{}不能为空'.format(fm_name)
					else:
						err_message = err_msg_dic['empty']
					is_valid = False
					fm_value = None

		else:
			pass

		ret['valid'] = is_valid
		ret['value'] = fm_value
		ret['msg'] = err_message

		return ret

	def all_valid(self, *args):
		"""
		获取所有表单验证整合结果，如有一个表单验证为False，则返回False；全为True，则返回True
		:param args: 传入所有表单验证结果>>>即传入每个表单fm_valid方法的返回值ret['valid'] = is_valid
		:return:
		"""

		valids = []

		for v in args:
			valids.append(v)

		# print str(valids)
		# print re.findall('False', str(valids))
		# 如果匹配到False>>>则将valids置为False
		if re.findall('False',str(valids)):
			valids = False
		else:
			valids = True

		return valids

	def fl_upload(self, handler, fm_name, valid=None, get_method=None, path='static'):
		"""
		若表单type为file，当所有表单验证整合结果为True时，则上传文件，否则不上传
		:param handler:
		:param fm_name: 字段的name属性值
		:param valid: 所有表单验证整合结果>>>即传入all_valid方法的返回值
		:param get_method: 上传时，该文件的获取方法（考虑到其他框架的扩展，所以...，若为tornado则默认即可）
		:param path: 上传文件时，该文件的保存路径
		:return:
		"""

		value = None
		# value = []  # 若考虑同一个fm_name用于多个文件，则可用列表接收文件名
		if valid:  # 如果valids为真(即valid中所有值都为True)，则上传文件
			if not get_method or get_method == 'self.request.files[]':
				try:
					file_obj = handler.request.files[fm_name]

					for meta in file_obj:
						file_name = meta['filename']
						with open(os.path.join(path, file_name), 'wb') as up:
							up.write(meta['body'])
							val = os.path.join(path, file_name)
							value = val
							# value.append(val)
				except:
					pass
			else:
				pass

		else:
			pass

		return value